package zlogger

import (
	"fmt"
	"github.com/natefinch/lumberjack"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"os"
	"strings"
	"time"
)

// HookLogNode 日志节点
type ZLogNode struct {
	// 等级
	Level string `xml:"level,attr"`
	// 是否写文件
	File int `xml:"file,attr"`
	// 是否写屏幕
	Console int `xml:"console,attr"`
}

// 设置zap日志的文件写入属性
func getZapLogWriter() zapcore.WriteSyncer {
	jackLogger := &lumberjack.Logger{
		Filename:   "./log/hook.log",     // 打印的日志文件名
		MaxSize:    1024,           // 切割大小，单位MB
		MaxAge:     30,                // 保存天数
		MaxBackups: 0,             // 文件保存个数,和上面个二选一
		LocalTime:  true,           // 是否使用本地时间,false是UTC时间
		Compress:   false,          // 是否压缩文件
	}
	return zapcore.AddSync(jackLogger)
}

// 日志格式
func getZapLogEncoder() zapcore.Encoder {
	// 时间自定义格式
	timeEncoder := func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
		enc.AppendString(t.Format("2006-01-02 15:04:05.000"))
	}
	cfg := zap.NewProductionEncoderConfig()
	cfg.EncodeTime = timeEncoder// 时间的显示格式
	cfg.EncodeLevel = zapcore.CapitalLevelEncoder  // 日志等级的显示格式(颜色)
	cfg.ConsoleSeparator = " " //字段的间隔方式，默认是\t, 这里改成了空格
	// 调用堆栈自定义
	callerEncoder := func(caller zapcore.EntryCaller, enc zapcore.PrimitiveArrayEncoder) {
		absPath := strings.Split(caller.File, "/")
		if len(absPath) < 1 {
			enc.AppendString(fmt.Sprintf("%s(%s:%d)", caller.Function, caller.File, caller.Line))
		} else {
			enc.AppendString(fmt.Sprintf("%s(%s:%d)", caller.Function, absPath[len(absPath)-1], caller.Line))
		}
	}
	cfg.EncodeCaller = callerEncoder
	return zapcore.NewConsoleEncoder(cfg)
}

func getZapLogLevel(logLevel *string) zapcore.Level {
	switch strings.ToLower(*logLevel) {
	case "debug":
		return zapcore.DebugLevel
	case "info":
		return  zapcore.InfoLevel
	case "warn":
		return  zapcore.WarnLevel
	case "error":
		return zapcore.ErrorLevel
	case "fatal":
		return zapcore.FatalLevel
	default:
		return zapcore.DebugLevel
	}
	return zapcore.DebugLevel
}

// 初始化日志实例
func InitLogger(logNode *ZLogNode) {
	fmt.Println("[日志] 开始初始化日志模块")
	encoder := getZapLogEncoder() // 日志格式
	var writer zapcore.WriteSyncer
	if logNode.File > 0 {
		writer = zapcore.NewMultiWriteSyncer(getZapLogWriter(), zapcore.AddSync(os.Stdout)) // 日志打印流向
	} else {
		writer = os.Stdout
	}
	logger := zap.New(zapcore.NewCore(encoder,
		writer,
		getZapLogLevel(&logNode.Level)), //日志等级
		zap.AddCaller()) //有了这行,才会打印文件和行数
	zap.ReplaceGlobals(logger)
	zap.S().Info("[日志] 初始化成功")
}
